from turtle import st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta


# 设置中文字体
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题
# hiu和
# 页面设置
st.set_page_config(
    page_title="财产保险成本费用分析系统",
    page_icon="📊",
    layout="wide",
    initial_sidebar_state="expanded"
)
# 黑寡妇
# 标题
st.title("财产保险成本费用分析系统")
# 是否
# 侧边栏 - 筛选器
with st.sidebar:
    st.header("筛选条件")

    # 时间范围选择
    time_periods = {
        "最近3个月": 3,
        "最近6个月": 6,
        "最近12个月": 12,
        "最近24个月": 24
    }
    selected_period = st.selectbox("时间范围", list(time_periods.keys()))
    months = time_periods[selected_period]

    # 险种选择
    business_types = ["全部", "车险", "企财险", "工程险", "责任险", "农险"]
    selected_type = st.selectbox("险种类型", business_types)

    # 区域选择
    regions = ["全部", "华东", "华北", "华南", "西南", "西北", "东北"]
    selected_region = st.selectbox("区域", regions)

    # 刷新数据按钮
    if st.button("刷新数据"):
        st.session_state.data_updated = True


# 模拟数据生成
@st.cache_data
def generate_insurance_cost_data(months=12):
    # 设置随机种子以确保结果可重现
    np.random.seed(42)

    # 生成时间序列
    dates = pd.date_range(end=datetime.now(), periods=months, freq='MS')

    # 基础数据生成
    earned_premium = np.random.randint(5000000, 20000000, months)  # 已赚保费
    incurred_loss = np.random.randint(2500000, 12000000, months)  # 已发生赔款
    underwriting_expenses = np.random.randint(1000000, 4000000, months)  # 承保费用
    commission_expenses = np.random.randint(500000, 2000000, months)  # 手续费及佣金
    reinsurance_expenses = np.random.randint(200000, 1000000, months)  # 分保费用

    # 创建DataFrame
    df = pd.DataFrame({
        'date': dates,
        'earned_premium': earned_premium,
        'incurred_loss': incurred_loss,
        'underwriting_expenses': underwriting_expenses,
        'commission_expenses': commission_expenses,
        'reinsurance_expenses': reinsurance_expenses
    })

    # 计算关键指标
    df['loss_ratio'] = df['incurred_loss'] / df['earned_premium'] * 100  # 赔付率
    df['expense_ratio'] = df['underwriting_expenses'] / df['earned_premium'] * 100  # 综合费用率
    df['combined_ratio'] = df['loss_ratio'] + df['expense_ratio']  # 综合成本率
    df['premium_expense_ratio'] = (df['underwriting_expenses'] + df['commission_expenses']) / df[
        'earned_premium'] * 100  # 保费费用率
    df['commission_ratio'] = df['commission_expenses'] / df['earned_premium'] * 100  # 手续费及佣金比率
    df['reinsurance_ratio'] = df['reinsurance_expenses'] / df['earned_premium'] * 100  # 分保费用比率

    # 添加一些季节性波动和趋势
    seasonal_factors = [1.1, 1.2, 0.9, 0.8, 1.0, 1.3, 1.2, 1.0, 0.9, 1.1, 1.3, 1.2]
    trend_factor = np.linspace(1.0, 1.1, months)

    for i in range(months):
        factor = seasonal_factors[i % 12] * trend_factor[i]
        df.loc[i, 'earned_premium'] *= factor
        df.loc[i, 'incurred_loss'] *= factor * np.random.uniform(0.9, 1.1)
        df.loc[i, 'underwriting_expenses'] *= factor * np.random.uniform(0.95, 1.05)
        df.loc[i, 'commission_expenses'] *= factor * np.random.uniform(0.9, 1.1)
        df.loc[i, 'reinsurance_expenses'] *= factor * np.random.uniform(0.85, 1.15)

    # 重新计算指标以反映调整后的数据
    df['loss_ratio'] = df['incurred_loss'] / df['earned_premium'] * 100
    df['expense_ratio'] = df['underwriting_expenses'] / df['earned_premium'] * 100
    df['combined_ratio'] = df['loss_ratio'] + df['expense_ratio']
    df['premium_expense_ratio'] = (df['underwriting_expenses'] + df['commission_expenses']) / df['earned_premium'] * 100
    df['commission_ratio'] = df['commission_expenses'] / df['earned_premium'] * 100
    df['reinsurance_ratio'] = df['reinsurance_expenses'] / df['earned_premium'] * 100

    # 确保指标在合理范围
    df['loss_ratio'] = df['loss_ratio'].clip(40, 80)
    df['expense_ratio'] = df['expense_ratio'].clip(20, 40)
    df['combined_ratio'] = df['combined_ratio'].clip(60, 110)
    df['premium_expense_ratio'] = df['premium_expense_ratio'].clip(30, 50)
    df['commission_ratio'] = df['commission_ratio'].clip(10, 25)
    df['reinsurance_ratio'] = df['reinsurance_ratio'].clip(5, 15)

    return df


# 加载数据
df = generate_insurance_cost_data(months)

# 显示最新数据概览
latest_data = df.iloc[-1].copy()
previous_data = df.iloc[-2].copy()

# 格式化日期
latest_data['date'] = latest_data['date'].strftime('%Y-%m-%d')
previous_data['date'] = previous_data['date'].strftime('%Y-%m-%d')


# 指标卡片样式
def metric_card(title, value, delta=None, unit="", is_percent=True, color="primary"):
    if is_percent:
        value_str = f"{value:.2f}%"
        if delta is not None:
            delta_str = f"{delta:.2f}%"
    else:
        if value >= 1e6:
            value_str = f"{value / 1e6:.2f}M"
        elif value >= 1e3:
            value_str = f"{value / 1e3:.2f}K"
        else:
            value_str = f"{value}"

        if delta is not None:
            if delta >= 1e6:
                delta_str = f"{delta / 1e6:.2f}M"
            elif delta >= 1e3:
                delta_str = f"{delta / 1e3:.2f}K"
            else:
                delta_str = f"{delta}"

    if delta is not None:
        delta_color = "normal"
        if delta > 0:
            delta_color = "positive" if "ratio" in title.lower() else "negative"
        elif delta < 0:
            delta_color = "negative" if "ratio" in title.lower() else "positive"

        st.metric(
            label=title,
            value=value_str,
            delta=delta_str if delta is not None else None,
            delta_color=delta_color
        )
    else:
        st.markdown(f"""
            <div class="metric-card" style="background-color: #f0f2f6; border-radius: 10px; padding: 1rem; margin-bottom: 1rem;">
                <div style="font-size: 0.875rem; color: #6b7280; margin-bottom: 0.25rem;">{title}</div>
                <div style="font-size: 1.5rem; font-weight: bold; color: {'#165DFF' if color == 'primary' else '#333'}">{value_str}</div>
            </div>
        """, unsafe_allow_html=True)


# 主要指标展示
st.header("关键指标概览")
col1, col2, col3 = st.columns(3)
with col1:
    metric_card(
        "赔付率",
        latest_data['loss_ratio'],
        latest_data['loss_ratio'] - previous_data['loss_ratio']
    )
    metric_card(
        "手续费及佣金比率",
        latest_data['commission_ratio'],
        latest_data['commission_ratio'] - previous_data['commission_ratio']
    )
with col2:
    metric_card(
        "综合费用率",
        latest_data['expense_ratio'],
        latest_data['expense_ratio'] - previous_data['expense_ratio']
    )
    metric_card(
        "分保费用比率",
        latest_data['reinsurance_ratio'],
        latest_data['reinsurance_ratio'] - previous_data['reinsurance_ratio']
    )
with col3:
    metric_card(
        "综合成本率",
        latest_data['combined_ratio'],
        latest_data['combined_ratio'] - previous_data['combined_ratio']
    )
    metric_card(
        "保费费用率",
        latest_data['premium_expense_ratio'],
        latest_data['premium_expense_ratio'] - previous_data['premium_expense_ratio']
    )

# 图表区域
st.header("成本费用趋势分析")

# 成本指标趋势
fig1, ax1 = plt.subplots(figsize=(15, 7))

ax1.plot(df['date'], df['loss_ratio'], 'b-', label='赔付率')
ax1.plot(df['date'], df['expense_ratio'], 'g-', label='综合费用率')
ax1.plot(df['date'], df['combined_ratio'], 'r-', label='综合成本率')
ax1.axhline(y=100, color='gray', linestyle='--', alpha=0.5, label='盈亏平衡点')

ax1.set_title('主要成本指标趋势')
ax1.set_xlabel('日期')
ax1.set_ylabel('比率 (%)')
ax1.legend()
ax1.grid(True)

plt.tight_layout()
st.pyplot(fig1)

# 费用构成分析
fig2, ax2 = plt.subplots(figsize=(15, 7))

bottom = np.zeros(len(df))

ax2.bar(df['date'], df['underwriting_expenses'] / df['earned_premium'] * 100,
        label='承保费用占比', bottom=bottom, color='#165DFF')
bottom += df['underwriting_expenses'] / df['earned_premium'] * 100

ax2.bar(df['date'], df['commission_expenses'] / df['earned_premium'] * 100,
        label='手续费及佣金占比', bottom=bottom, color='#3B82F6')
bottom += df['commission_expenses'] / df['earned_premium'] * 100

ax2.bar(df['date'], df['reinsurance_expenses'] / df['earned_premium'] * 100,
        label='分保费用占比', bottom=bottom, color='#60A5FA')

ax2.set_title('费用构成占比分析')
ax2.set_xlabel('日期')
ax2.set_ylabel('占保费收入比例 (%)')
ax2.legend()
ax2.grid(True)

plt.tight_layout()
st.pyplot(fig2)

# 成本与保费关系分析
fig3, (ax3, ax4) = plt.subplots(1, 2, figsize=(15, 7))

# 赔付率与保费收入关系
ax3.scatter(df['earned_premium'] / 10000, df['loss_ratio'], alpha=0.7)
ax3.set_title('赔付率 vs 保费收入')
ax3.set_xlabel('保费收入 (万元)')
ax3.set_ylabel('赔付率 (%)')
ax3.grid(True)

# 综合成本率与保费收入关系
ax4.scatter(df['earned_premium'] / 10000, df['combined_ratio'], alpha=0.7)
ax4.axhline(y=100, color='red', linestyle='--', alpha=0.5, label='盈亏平衡点')
ax4.set_title('综合成本率 vs 保费收入')
ax4.set_xlabel('保费收入 (万元)')
ax4.set_ylabel('综合成本率 (%)')
ax4.legend()
ax4.grid(True)

plt.tight_layout()
st.pyplot(fig3)

# 数据表格
st.header("详细数据")
df_display = df.copy()
df_display['date'] = df_display['date'].dt.strftime('%Y-%m-%d')

# 格式化金额列
amount_cols = [
    'earned_premium', 'incurred_loss', 'underwriting_expenses',
    'commission_expenses', 'reinsurance_expenses'
]

for col in amount_cols:
    df_display[col] = df_display[col].apply(lambda x: f"{x / 10000:.2f}万元")

# 格式化百分比列
percent_cols = [
    'loss_ratio', 'expense_ratio', 'combined_ratio',
    'premium_expense_ratio', 'commission_ratio', 'reinsurance_ratio'
]

for col in percent_cols:
    df_display[col] = df_display[col].apply(lambda x: f"{x:.2f}%")

# 重新排序列
display_order = [
    'date', 'earned_premium', 'incurred_loss', 'loss_ratio',
    'underwriting_expenses', 'commission_expenses', 'reinsurance_expenses',
    'expense_ratio', 'commission_ratio', 'reinsurance_ratio',
    'premium_expense_ratio', 'combined_ratio'
]

df_display = df_display[display_order]

# 重命名列
new_names = {
    'date': '日期',
    'earned_premium': '已赚保费',
    'incurred_loss': '已发生赔款',
    'loss_ratio': '赔付率',
    'underwriting_expenses': '承保费用',
    'commission_expenses': '手续费及佣金',
    'reinsurance_expenses': '分保费用',
    'expense_ratio': '综合费用率',
    'commission_ratio': '手续费及佣金比率',
    'reinsurance_ratio': '分保费用比率',
    'premium_expense_ratio': '保费费用率',
    'combined_ratio': '综合成本率'
}

df_display = df_display.rename(columns=new_names)

# 显示表格
st.dataframe(df_display)

# 页脚
st.markdown("""
<style>
footer {
    visibility: hidden;
}
</style>
""", unsafe_allow_html=True)